Skip to content

Fix composite and include listeners, and try the listener method taking the event first - #6158

Merged
BalusC merged 1 commit into
4.0from
listener_one_arg_first
Nov 11, 2026
Merged

BalusC merged 1 commit into
4.0from
listener_one_arg_first

Conversation

@BalusC

@BalusC BalusC commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #6157

<f:event listener>, <f:ajax listener>, actionListener and valueChangeListener accept a method taking the event or a method taking no arguments. Mojarra creates a MethodExpression per variant and falls back to the other one on MethodNotFoundException.

Composite component listeners. ContextualCompositeMethodExpression.invoke() looks for the method expression of an outer composite component when its delegate throws MethodNotFoundException. When that lookup failed with PropertyNotFoundException, it threw that one, so the caller never fell back to the other variant. A composite actionListener or valueChangeListener with a bean method without arguments failed with HTTP 500. A composite <f:event> or <f:ajax> listener with a method-signature taking the event got null as event on GlassFish, and failed on Tomcat. The lookup is now extracted into invokeOuterCompositeMethodExpression(), which throws the original MethodNotFoundException when the outer expression does not resolve or is no method expression. Any other exception of the lookup or of the invoked outer method still propagates.

valueChangeListener in an include or tag file. EditableValueHolderRule now creates the variant without arguments through the tag attribute, as ActionSourceRule does, and passes both variants to MethodExpressionValueChangeListener(MethodExpression, MethodExpression). The one-argument constructor created that variant without the variable mapper of the Facelet context, so a method without arguments of a bean from ui:param or a tag file attribute failed with "Target Unreachable".

Order. <f:event> and <f:ajax> now try the variant taking the event first, on each invocation, as MethodExpressionActionListener.processAction() specifies. ListenerMethodInvoker does this for both tags.

Behavior change. For <f:event> and <f:ajax>, a bean which has both m() and m(event) now gets m(event), as actionListener and valueChangeListener already do, and as MyFaces does for <f:event>. The same holds for a method taking varargs, which now gets the event. In Development stage, Mojarra logs JSF1113 once per listener for a bean with both methods. The specification does not define this case yet, see jakartaee/faces#2274.

Tests: ListenerMethodInvokerTest, DeserializedListenerTest, ContextualCompositeMethodExpressionTest, and Issue6157IT with 37 cases, green on GlassFish. The IT covers every row of the table in jakartaee/faces#2274, and these listener syntaxes on all four attributes: #{b.m()}, #{b.m(component)}, #{b.m('x')}, #{b['m']}, a method taking a supertype of the event, Object or varargs, a method returning a value, a bean from ui:param, a tag file attribute or a composite component attribute, a method call given to a composite component method attribute, c:forEach, ui:repeat and h:dataTable with the var as argument, f:actionListener and f:valueChangeListener with binding="#{b.m()}", and ui:repeat over beans of different classes. Against the 4.0 branch, 11 of them fail.

🤖 Generated with Claude Opus 5.5

ContextualCompositeMethodExpression.invoke() throws the original
MethodNotFoundException when the outer composite method expression
does not resolve, so the caller falls back to the other variant.

f:event and f:ajax try the listener method taking the event first,
on each invocation, as MethodExpressionActionListener does. In
Development, JSF1113 warns once per listener when the bean also has
the method taking no arguments.

valueChangeListener creates both variants through the tag attribute,
so a method without arguments resolves the variables of an include
or tag file.

Fixes #6157

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BalusC
BalusC force-pushed the listener_one_arg_first branch from 1f68db3 to f187647 Compare November 11, 2026 11:47
@BalusC BalusC changed the title Fix composite listeners and remember the listener method variant Fix composite and include listeners, and try the listener method taking the event first Nov 11, 2026
@BalusC
BalusC merged commit 53d069e into 4.0 Nov 11, 2026
2 checks passed
@BalusC
BalusC deleted the listener_one_arg_first branch November 11, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant